﻿using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Tilemaps;
using UnityEngine.UI;

namespace SLG_Demo_0
{
	/// <summary>
	/// 地图显示信息
	/// </summary>
	//public class MapDisplay : MonoBehaviour_Singleton<MapDisplay>
	public class MapDisplay
	{
		/// <summary>
		/// 所属地图对象
		/// </summary>
		private MapObject m_pMapObject = null;

		/// <summary>
		/// 地图宽高
		/// </summary>
		private int m_width = 0, m_height = 0;

		/// <summary>
		/// 显示用的摄像机
		/// </summary>
		//public Camera Camera.main = null;

		/// <summary>
		/// 需要指定的 UnityEngine.Tilemaps.Tilemap 地图对象
		/// </summary>
		public Tilemap m_TileMap = null;

		/// <summary>
		/// 需要指定的，当前地图格子显示用的精灵
		/// </summary>
		public Sprite m_Sprite = null;

		/// <summary>
		/// 显示用的所有地图格子
		/// </summary>
		public CellDisplay[,] m_Cells;

		//出生格子
		List<CellData> bornGrids = new List<CellData>();
		//普通格子
		List<CellData> normalGrids = new List<CellData>();
		//障碍格子
		List<CellData> obstacleGrids = new List<CellData>();

		// 上次选中的格子
		private CellDisplay m_LastCell = null;

		// 测试...
		private int m_TestSec = 5;

		// 选中的起点和终点
		private CellData m_pCellBegin = null;
		private CellData m_pCellEnd = null;
		List<CellData> m_lPath = null;

		////////////////////////////////////////////////////////////
		public MapDisplay(Tilemap rTilemap, Sprite rSprite)
		{
			m_TileMap = rTilemap;
			m_Sprite = rSprite;
		}

		/*private GameObject NewCellInfo(int nRow, int nCol)
		{
			GameObject prefabCellInfo = AssetDatabase.LoadAssetAtPath<GameObject>("Assets/Prefabs/" + "CellInfo.prefab");
			Text text = prefabCellInfo.GetComponentInChildren<Text>();
			text.text = "(" + nRow + ", " + nCol + ")";

			RectTransform rectTransform = prefabCellInfo.GetComponent<RectTransform>();
			rectTransform.localScale = new Vector3(0.015625f, 0.015625f, 1);
			rectTransform.position = new Vector3(0, -0.1f, 0);
			Object.Instantiate(prefabCellInfo);

			return prefabCellInfo;
		}*/

		/// <summary>
		/// 创建显示用的地图
		/// </summary>
		public void Create(MapObject pMapObj, int nWidth, int nHeight)
		{
			m_pMapObject = pMapObj;
			Create(nWidth, nHeight);
		}

		/// <summary>
		/// 创建显示用的地图
		/// </summary>
		public void Create(int nWidth, int nHeight)
		{
			m_width = nWidth;
			m_height = nHeight;

			m_Cells = new CellDisplay[m_width, m_height];
			for (int iRow = 0; iRow < m_height; ++iRow)
			{
				for (int iCol = 0; iCol < m_width; ++iCol)
				{
					CellDisplay cell = ScriptableObject.CreateInstance<CellDisplay>();
					cell.Create(m_pMapObject, iRow, iCol, m_Sprite);
					//cell.gameObject = NewCellInfo(iRow, iCol);
					m_Cells[iRow, iCol] = cell;

					m_TileMap.SetTile(new Vector3Int(iRow, iCol, 0), cell);
				}
			}

			// 显示的不正确应该去调整摄像机。自动将摄像机调整至地图中心
			Vector3 cameraPos = CellToWorld(m_width / 2, m_height / 2);
			// 注意最后一个参数的设置，是原来摄像机的深度，只能放在最后一步，放在 mapCenter 设置原来的深度是没有用的
			Camera.main.transform.position = new Vector3(cameraPos.x, cameraPos.y, (int)Camera.main.transform.position.z);
		}

		// 将地图所有颜色置为初始状态
		public void Clear()
		{
			for (int iRow = 0; iRow < m_height; ++iRow)
			{
				for (int iCol = 0; iCol < m_width ; ++iCol)
				{
					CellDisplay cellDisplay = GetCellDisplay(iRow, iCol);
					if (cellDisplay != null)
					{
						cellDisplay.DisplayType = ECellDisplayType.Normal;
					}
				}
			}
			m_pMapObject.RefreshInitMap();
		}

		public CellDisplay GetCellDisplay(int nRow, int nCol)
		{
			Vector3Int cellPos = new Vector3Int(nRow, nCol, 0);
			CellDisplay cell = m_TileMap.GetTile<CellDisplay>(cellPos);
			return cell;
		}

		// TODO：这个转换函数和显示无关，应移动到 MapObject 中
		public Vector3Int MousePos2TilePos(Vector3 nMousePos)
		{
			nMousePos.z = Camera.main.transform.position.z;
			Vector3 mouseWorldPos = Camera.main.ScreenToWorldPoint(nMousePos);
			Vector3 mouseLocalPos = m_TileMap.WorldToLocal(mouseWorldPos);
			Vector3Int cellPos = m_TileMap.WorldToCell(mouseLocalPos);

			return cellPos;
		}

		/// <summary>
		/// 把格子的 XY 坐标转换成世界坐标。
		/// TODO：这个转换函数和显示无关，应移动到 MapObject 中
		/// </summary>
		/// <param name="X"></param>
		/// <param name="Y"></param>
		/// <returns></returns>
		public Vector3 CellToWorld(int X, int Y)
		{
			Vector3Int cellPos = new Vector3Int(X, Y, 0);
			Vector3 transPos = m_TileMap.CellToWorld(cellPos);
			return transPos;
		}

		/// <summary>
		/// 把世界坐标转换成格子的 XY 坐标
		/// TODO：这个转换函数和显示无关，应移动到 MapObject 中
		/// </summary>
		/// <param name="X"></param>
		/// <param name="Y"></param>
		/// <returns></returns>
		public Vector2Int WorldToCell(Vector3 position)
		{
			Vector3Int transPos = m_TileMap.WorldToCell(position);
			Vector2Int cellpos = new Vector2Int(transPos.x, transPos.y);
			return cellpos;
		}

		void UpdateCamera()
		{
			float ratioMove = 5.0f;

			// 键盘控制摄像机深度
			if (Input.GetKey(KeyCode.W))
			{
				Camera.main.orthographicSize -= Time.deltaTime * ratioMove;
			}
			else if (Input.GetKey(KeyCode.S))
			{
				Camera.main.orthographicSize += Time.deltaTime * ratioMove;
			}

			// 鼠标滚轮控制摄像机深度
			//Zoom out
			if (Input.GetAxis("Mouse ScrollWheel") < 0)
			{
				Camera.main.orthographicSize += Time.deltaTime * ratioMove;
			}
			//Zoom in
			if (Input.GetAxis("Mouse ScrollWheel") > 0)
			{
				Camera.main.orthographicSize -= Time.deltaTime * ratioMove;
			}
		}

		// 真正的入口，因为要渲染地图
		// Start is called before the first frame update
		void Start()
		{
			// 必须使用正交摄像机，否则 Tilemap.WorldToLocal() 无法转换得到正确的坐标
			if (!Camera.main.orthographic)
			{
				Debug.LogError("Camera.main must be set to orthographic (Attribute [Projection] in Inspector)");
			}

			//Create(5, 5);
		}

		// Update is called once per frame
		public void Update()
		{
			// 测试...
			/*CellDisplay cell_1_0 = GetCellDisplay(1, 0);
			if (cell_1_0 != null)
			{
				if (m_TestSec > 0)
				{
					cell_1_0.DisplayType = ECellDisplayType.Searched;
				}
				else
				{
					cell_1_0.DisplayType = ECellDisplayType.Normal;
				}

				--m_TestSec;
			}*/



			Vector3 mousePos = new Vector3(0.0f, 0.0f, 0.0f);// 屏幕左下角为(0, 0)
			Vector3 mouseWorldPos = new Vector3(0.0f, 0.0f, 0.0f);

			UpdateCamera();

			//如果点击了鼠标左键
			if (Input.GetMouseButtonDown(0))
			{
				//
			}
			m_TileMap.RefreshAllTiles();

			// 鼠标左键抬起
			if (Input.GetMouseButtonUp(0))
			{
				//Debug.Log("Input Pos: (" + Input.mousePosition.x + ", " + Input.mousePosition.y + ")");

				if (m_pMapObject.m_bShowSearch)
				{
					Clear();

					Vector3Int cellPos = MousePos2TilePos(Input.mousePosition);
					CellDisplay cell = m_TileMap.GetTile<CellDisplay>(cellPos);
					if (cell != null)
					{
						if (cell.DisplayType == ECellDisplayType.Normal)
						{
							cell.DisplayType = ECellDisplayType.Selected;
						}
						else if (cell.DisplayType == ECellDisplayType.Selected)
						{
							cell.DisplayType = ECellDisplayType.Normal;
						}

						if (m_LastCell != cell)
						{
							Debug.Log("Cell Pos: (" + cell.X + ", " + cell.Y + ")");
						}

						m_LastCell = cell;

						m_pCellBegin = cell.GetData();
					}
				}//end if (m_bShowSearch)

			}//end if (Input.GetMouseButtonUp(0))

			// 鼠标右键抬起
			if (Input.GetMouseButtonUp(1))
			{
				if (m_pMapObject.m_bShowSearch)
				{
					Vector3Int cellPos = MousePos2TilePos(Input.mousePosition);
					CellDisplay cell = m_TileMap.GetTile<CellDisplay>(cellPos);
					if (cell != null)
					{
						m_pCellEnd = cell.GetData();

						if (m_pCellBegin != null && m_pCellEnd != null)
						{
							m_lPath = new List<CellData>();
							bool bRet = PathFinding.Instance.Search(m_pMapObject.MapData, m_pCellBegin, m_pCellEnd, m_lPath);
							if (bRet)
							{
								for (int iPath = 0; iPath < m_lPath.Count; ++iPath)
								{
									CellDisplay cellDisplay = GetCellDisplay(m_lPath[iPath].Row, m_lPath[iPath].Col);
									if (iPath < m_lPath.Count - 1)
									{
										if (cellDisplay.IsStaticType())
										{
											cellDisplay.DisplayType = ECellDisplayType.PathAtStatic;
										}
										else
										{
											cellDisplay.DisplayType = ECellDisplayType.Path;
										}
									}
									else
									{
										cellDisplay.DisplayType = ECellDisplayType.End;
									}
								}//eod for: iPath
							}
						}
					}
				}//end if (m_bShowSearch)
			}//end if (Input.GetMouseButtonUp(1))
		}
	}
}
